package org.apache.ibatis.plugin;

import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Properties;

/**
 * #mark 输出执行时间插件
 *
 * @author rain.wen
 * @date 2018/1/3.
 */
@Intercepts({
        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class,}),
        @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})
})
public class ExecutionTimePlugin implements Interceptor {

    private final static Logger logger = LoggerFactory.getLogger(ExecutionTimePlugin.class);

    private static boolean showTime = Boolean.FALSE;

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        if(!showTime) {
            return invocation.proceed();
        }

        long begin = System.currentTimeMillis();
        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
        try {
            return invocation.proceed();
        } finally {
            if(logger.isDebugEnabled()) {
                logger.debug("==> [time {}] {} ", System.currentTimeMillis() - begin, mappedStatement.getId());
            }
        }

    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
        String property = properties.getProperty("showTime", "false");
        if(property != null && property.length() > 0) {
            showTime = property.equalsIgnoreCase("false") ? Boolean.FALSE : Boolean.TRUE;
        }
    }
}
